package com.dcy.znoa.service.publiz.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dcy.znoa.common.exception.BusinessException;
import com.dcy.znoa.common.util.RedisClient;
import com.dcy.znoa.common.util.pojo.JsonCommon;
import com.dcy.znoa.common.util.pojo.JsonForList;
import com.dcy.znoa.controller.publiz.model.SelectBaseModel;
import com.dcy.znoa.controller.publiz.model.department.SelectDepartmentModel;
import com.dcy.znoa.controller.publiz.model.oper.SelectOperModel;
import com.dcy.znoa.dao.publiz.CompanyDao;
import com.dcy.znoa.dao.publiz.DepartmentDao;
import com.dcy.znoa.dao.user.OperDao;
import com.dcy.znoa.domain.Oper;
import com.dcy.znoa.domain.publiz.Company;
import com.dcy.znoa.domain.publiz.Department;
import com.dcy.znoa.service.publiz.DepartmentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import static com.dcy.znoa.common.util.RedisClient.*;
import static com.dcy.znoa.domain.publiz.Department.TO_AUDIT;

/**
 * @author pengyu
 */
@Slf4j
@Service
public class DepartmentServiceImpl implements DepartmentService {

    @Autowired
    DepartmentDao departmentDao;
    @Autowired
    OperDao operDao;
    @Autowired
    CompanyDao companyDao;

    @Autowired
    ThreadPoolTaskExecutor defaultExecutor;

    @Override
    public JsonForList selectList(SelectDepartmentModel model) throws InvocationTargetException, IllegalAccessException {
        List<Department> list;
        EntityWrapper<Department> ew = new EntityWrapper<>();
        if (model.getCompId() != null && model.getCompId() > 0) {
            ew.eq("comp_id", model.getCompId());
        }
        if (model.getPDepId() != null && model.getPDepId() > 0) {
            ew.eq("p_dep_id", model.getPDepId());
        }
//        ew.like("comp_name", model.getCompName())
        ew.like("contact_man", model.getContactMan())
                .like("dep_name", model.getDepName());
//                .like("p_dep_name", model.getPDepName())
//                .like("comp_name", model.getCompName());
        if (model.getCreateOperId() != null && model.getCreateOperId() > 0) {
            ew.eq("create_oper_id", model.getCreateOperId());
        }
        if (model.getUpdateOperId() != null && model.getUpdateOperId() > 0) {
            ew.eq("update_oper_id", model.getUpdateOperId());
        }
        if (model.getValidFlag() != null) {
            ew.eq("valid_flag", model.getValidFlag());
        }
        ew.ne("dep_name",TO_AUDIT);//不查询TO_AUDIT的
        Integer total = SelectBaseModel.PageFill(model, ew, departmentDao);//加入分页参数
//        ew.eq("valid_flag",1);
        list = departmentDao.selectList(ew);
        if (list.isEmpty()) {
            return new JsonForList(JsonCommon.NOT_FOUND_CODE);
        }
        return new JsonForList(list,total);
    }

    @Override
    public JsonForList selectByCompId(int compId) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        if (compId <= 0) {
            return new JsonForList(null, "compId  不能小于等于0");
        }
        //从redis中查询
        JsonForList json = getJsonListfromRedisOfJson(COMP_DEP_PREFIX + String.valueOf(compId));
        if (json != null) {
            return json;
        }
        //默认查询valid_flag =1的
        List<Department> compDepList = departmentDao.selectList(new EntityWrapper<Department>().eq("comp_id", compId).eq("dep_level", 1).eq("valid_flag",1));
        if (compDepList.isEmpty()) {
//            return new JsonForList(JsonCommon.NOT_FOUND_CODE);
            return new JsonForList(JsonCommon.SUCCESS_CODE,"无下级部门");
        }
        for (Department dep : compDepList) {
            querySubDepinfo(compId, dep);
        }
        //放入redis  暂时屏蔽
        putListToRedisOfJson(COMP_DEP_PREFIX + String.valueOf(compId), compDepList);
        return new JsonForList(compDepList, JsonCommon.SUCCESS_CODE, JsonCommon.SUCCESS_MSG);
    }

    private void querySubDepinfo(int compId, Department dep) {
        //查询本级对应的管理员、雇员
//            List<Oper> list = operDao.selectListMapper(new EntityWrapper<Oper>().eq("comp_id",compId).eq("p_dep_id",dep.getDepId()));
//        List<Oper> operList = operDao.selectListMapper(new EntityWrapper<Oper>().eq("comp_id", compId).eq("dep_id", dep.getDepId()).orderBy("duty_no"));//按 职务序号 排正序
        SelectOperModel model = new SelectOperModel();
        model.setCompId((long) compId);
        model.setDepId(dep.getDepId());
        List<Oper> operList = operDao.selectListMapper( model ,new Page(1,1000));
        List<Oper> managerList = new ArrayList<>();//部门负责人
        List<Oper> employeeList = new ArrayList<>();//部门普通员工,雇员
        for (Oper oper : operList) {
            if (oper.getIsDepDuty() !=null && oper.getIsDepDuty() == 1) {
                managerList.add(oper);
            } else {
                employeeList.add(oper);
            }
        }
        dep.setManagerList(managerList);
        dep.setEmployeeList(employeeList);
        dep.setOperSize(operList.isEmpty() ? 0 : operList.size());
        //查询下级部门
        List<Department> subDepList = departmentDao.selectList(new EntityWrapper<Department>().eq("p_dep_id", dep.getDepId()).eq("valid_flag",1));
        if (!subDepList.isEmpty()) {
            for (Department subDep : subDepList) {
                querySubDepinfo(compId, subDep);
            }
            dep.setSubDepList(subDepList);
        }
    }

    @Override
    public JsonCommon insert(Department var1) throws BusinessException {
        if (var1.getDepLevel() != null && var1.getDepLevel() == 1) {
            Integer resultInt = departmentDao.selectCount(new EntityWrapper<Department>().eq("comp_id", var1.getCompId()).eq("dep_level", 1));
            if (resultInt != null || resultInt > 0) {
                throw new BusinessException("404", "根节点部门只能有一个！");
            }
        }
        //查询：同一个公司下不允许有同名的部门
        List list = departmentDao.selectList( new EntityWrapper<Department>().eq("comp_id",var1.getCompId()).eq("dep_name",var1.getDepName()).eq("valid_flag",1));
        if(!list.isEmpty()){
            return new JsonCommon(JsonCommon.INSERT_ERROR_CODE,"不允许有同名的部门");
        }
        Integer result = departmentDao.insert(var1);
        if (result == null || result <= 0) {
            return new JsonCommon(JsonCommon.INSERT_ERROR_CODE);
        }
        updateRedis(var1.getCompId());
        return new JsonCommon(JsonCommon.SUCCESS_CODE, JsonCommon.SUCCESS_MSG);
    }

    @Override
    public JsonCommon updateById(Department var1) throws BusinessException {
        //如果是顶级部门，不允许修改
        Department department =departmentDao.selectById(var1.getDepId());
        Integer depLevel = department.getDepLevel();
        if(depLevel !=null && depLevel == 1){
            return new JsonCommon(JsonCommon.INSERT_ERROR_CODE,"顶层部门不允许修改");
        }
        //检查是否有部门名，查询库里同名的部门是否有不同的id
        List<Department> list = departmentDao.selectList( new EntityWrapper<Department>().eq("comp_id",var1.getCompId()).eq("dep_name",var1.getDepName()).eq("valid_flag",1));
        boolean flag;
        if(list.isEmpty()){ //允许修改
            flag = true;
        }else if(list.size()==1){//判断id是不是一样的
            if(var1.getDepId().longValue() == list.get(0).getDepId().longValue()){//允许修改
                flag = true;
            }else{
                flag = false;
            }
        }else{// >1，不允许修改
            flag = false;
        }
        if(flag == false){
            return new JsonCommon(JsonCommon.UPDATE_ERROR_CODE,"存在同名部门，不允许修改");
        }
        //如果是禁用
        if(var1.getValidFlag()!=null && var1.getValidFlag() == 0){
            if(StringUtils.isNotBlank(var1.getDepName())&&var1.getDepName().equals(TO_AUDIT)){
                return new JsonCommon(JsonCommon.UPDATE_ERROR_CODE,TO_AUDIT+"部门不允许禁用或删除");
            }
            //如果部门下有员工，则不允许禁用
            List<Oper> operList = operDao.selectList( new EntityWrapper<Oper>().eq("dep_id",var1.getDepId()).eq("valid_flag",1));
            if(!operList.isEmpty()){
                return new JsonCommon(JsonCommon.UPDATE_ERROR_CODE,"部门下存在员工，不允许禁用");
            }
            //如果部门下有下级部门，则不允许禁用
            List<Department> subDepList = departmentDao.selectList( new EntityWrapper<Department>().eq("p_dep_id",var1.getDepId()).eq("valid_flag",1));
            if(!subDepList.isEmpty()){
                return new JsonCommon(JsonCommon.UPDATE_ERROR_CODE,"该部门存在下级部门，不允许禁用");
            }
        }
        Integer result = departmentDao.updateById(var1);
        if (result == null || result <= 0) {
            return new JsonCommon(JsonCommon.INSERT_ERROR_CODE);
        }
        log.info(var1.toString());
        if(department!= null ){
            updateRedis(department.getCompId());
        }
//        updateRedis(var1.getCompId());
        return new JsonCommon(JsonCommon.SUCCESS_CODE, JsonCommon.SUCCESS_MSG);
    }
    @Override
    public void updateRedis(Long compId) {
        log.info("begin updateRedis "+compId);
        if ( compId==null ||compId <= 0) {
            return;
        }
        final Runnable updateRedisTask = () -> {
            List<Department> compDepList = departmentDao.selectList(new EntityWrapper<Department>().eq("comp_id", compId).eq("dep_level", 1));
            if (compDepList.isEmpty()) {
                return;
            }
            for (Department dep : compDepList) {
                querySubDepinfo(Math.toIntExact(compId), dep);
            }
            //放入redis
            try {
                RedisClient.delByKey(COMP_DEP_PREFIX + String.valueOf(compId));
                putListToRedisOfJson(COMP_DEP_PREFIX + String.valueOf(compId), compDepList);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        };
        defaultExecutor.execute(updateRedisTask);
        log.info("end updateRedis "+compId);
    }

    @Transactional
    @Override
    public Integer deleteById(Long depId) {
        Department dep = departmentDao.selectById(depId);
        Long compId = dep.getCompId();
        departmentDao.deleteById(depId);
        updateRedis(compId);
        return 1;
    }

    @Override
    public List selectUpperByCompId() {
        return null;
    }
}